<?php
/***************************************************************************
                                   Mtest.php
                                ---------------
  
       A PHP4 class to build test suites for PHP scripts. 

       $Revision: 1.5 $
       $Date: 2006/02/04 11:19:53 $
       $Source: /cvsroot/phpmanta/phpManta/include/php4/Mtest.php,v $
       $Author: jmfaure $
       $Name: HEAD $

       /           phpManta <http://phpmanta.sourceforge.net/>
      / \
     /   \         Copyright (c) 2005-2006, JM Faure
   o/     \        <jmfaure at users dot sourceforge dot net>
   |       >-----
   o\     /        Redistribution and use in source and binary forms, 
     \   /         with or without  modification, are permitted provided
      \ /          that the BSD License conditions are met, please
       \           refer to: www.opensource.org/licenses/bsd-license.php

 **************************************************************************/

// Ensure this script is included by a parent file
if (realpath($_SERVER['SCRIPT_FILENAME']) == __FILE__) die("FILE ACESS METHOD NOT ALLOWED");

/**
 * Define few flags as constants.
 *
 * @public
 * @block
 */
define("MTEST_REGEX", true);  // Flag to use Perl regex in check_in_string() method.

/**
 * A class to test PHP scripts.
 *
 * This is a class designed to build test pages which can help to check scripts
 * stability over releases.
 *
 * @experimental
 */
class Mtest {

/** 
 * Count tests (used to print test numbers).
 *
 * @private
 * @type int
 */
var $counter = 0;

/** 
 * Store all test result messages.
 *
 * @private
 * @type array
 */
var $message = array();

/** 
 * Store all test boolean results.
 *
 * @private
 * @type array
 */
var $result = array();

/** 
 * Store all test titles.
 *
 * @private
 * @type array
 */
var $title = array();

/** 
 * Stack for variable tracking.
 *
 * A tracked variable is printed in
 * test results when test failed.
 *
 * @private
 * @type array
 */
var $tracker = array();

/** 
 * Stack of XHTML formatted output string.
 *
 * @private
 * @type array
 */
var $xout = array(
                'nl' => "<br />",
            );

/**
 * Create and reset a new Mtest instance.
 *
 * @return (object) a Mtest instance
 */
function Mtest() {

  // $counter and $results properties are created empty
}

/**
 * Add a variable tracker in current test.
 *
 * @public
 * @param (string) $tname the tracker name (usually varaiable name
 *                        in test (global) context)
 * @param (mixed) $tvar pointer to the tracked variable
 * @return (void)
 */
function add_tracker($tname, &$tvar) {

  // Get current test id
  $test_id = $this->counter;
  
  // Build the tracker
  $tracker = array($tname, $tvar);
  
  // Print negative feedback and quote results
  array_push($this->tracker[$test_id], $tracker);
}

/**
 * Check if a string occurs in a string result.
 *
 * @public
 * @param (string) $expected the expected result
 * @param (string) $result the result to check
 * @param (bool) $regex set it to true (or MTEST_REGEX)
 *                      to look for a Perl regex pattern
 * @return (void)
 */
function check_in_string($expected, $result, $regex = false) {

  // Process regex lookup
  if (MTEST_REGEX) {
    if (preg_match($expected, $result) === 1) {
      $test = true;
    } else {
      $test = false;
    }
  // Process string lookup
  } else {
    if (stristr($result, $expected) !== false) {
      $test = true;
    } else {
      $test = false;
    }
  }

  // Store test result
  $this->store_result($test, $expected);
}

/**
 * Check if a value is the expected result.
 *
 * @public
 * @param (string) $expected the expected result
 * @param (string) $result the result to check
 * @return (void)
 */
function check_is_equal($expected, $result) {

  // Process test
  $test = ($result == $expected);

  // Store test result
  $this->store_result($test, $expected);
}

/**
 * Check if a value is different from the expected result.
 *
 * @public
 * @param (string) $expected the expected result
 * @param (string) $result the result to check
 * @return (void)
 */
function check_is_not_equal($expected, $result) {

  // Process test
  $test = ($result != $expected);

  // Store test result
  $this->store_result($test, $expected);
}

/**
 * Return ID of current test.
 *
 * @public
 * @return (int) the current test ID
 */
function get_id() {

  return $this->counter;
}

/**
 * Return result of the previous test.
 *
 * @public
 * @return (mixed) the result of the previous test 
 *                 or NULL if can't establish a 
 *                 "previous" test nor its result 
 */
function get_previous_result() {

  // Can establish a "previous" test ?
  if ($this->counter < 2) {
    return NULL;
  }

  // Get current test id
  $test_id = $this->counter;
  
  // Return previous test result
  return $this->result[$test_id -1];
}

/**
 * Return title of current test.
 *
 * @public
 * @return (string) the current test title
 */
function get_title() {

  // No test yet
  if ($this->counter == 0) {
    return "Warning: no test iniated yet in this instance.";
  }

  return $this->title[$this->counter];
}

/**
 * Initiate a new test in the current instance.
 *
 * @public
 * @param (string) $title the new test title
 * @return (int) the test ID
 */
function new_test($title) {

  // Increment test counter (so is a test ID)
  $test_id = ++$this->counter;
  
  // Store test title
  $this->title[$test_id] = $title;
  
  // Reset test messages
  $this->message[$test_id] = array();
  
  // Reset test trackers
  $this->tracker[$test_id] = array();

  // Set test result status
  $this->result[$test_id] = null;
  
  // Return test ID
  return $test_id;
}

/**
 * Print the current test data stack.
 *
 * @public
 * @param (bool) $show_all Flag to show results in details, with the expected
 *                         test values (can produce confusing large output).
 * @return (void)
 */
function print_result($show_all = false) {

  // Get current test id
  $test_id = $this->counter;
  
  // Get new line formatted string
  $nl = $this->xout['nl'];
  
  // Get test title
  $test_title = $this->title[$test_id];
  
  // Ensure test was processed
  if ($this->result[$test_id] === null) {
    echo $nl;
    echo "<i>Test #{$test_id} not performed ({$test_title})</i>\n";
    return;
  }
  
  // Test passed ?
  if ($this->result[$test_id]) {
    // Print positive feedback with current test title
    echo $nl;
    echo "Test #{$test_id} passed : {$test_title}\n";
  } else {
    // Print negative feedback and quote results
    echo $nl;
    echo "<b class=\"failed\">Test #{$test_id} failed : {$test_title}</b>\n";
    echo "<blockquote>\n";
    // Unstack test result details (could be confusing with large varaibel content)
    if ($show_all) {
      foreach($this->message[$test_id] as $test_result) {
        $fres = print_r($test_result, true);
        echo $nl;
        echo "<pre>\n{$fres}\n</pre>\n";
      }
    }
    // Unstack the trackers
    if (!empty($this->tracker[$test_id])) {
      echo "<blockquote>\n";
      foreach ($this->tracker[$test_id] as $tracker) {
        $tname = $tracker[0];
        $tvar = htmlentities(print_r($tracker[1], true));
        echo $nl;
        echo "<b class=\"variable\">{$tname}</b>\n";
        echo $nl;
        echo "<pre>\n{$tvar}\n</pre>\n";
      }
      echo "</blockquote>\n";
    }
    echo "</blockquote>\n";
  }
}

/**
 * Store a test result in the current test data stack.
 *
 * @private
 * @param (bool) $passed the test result, true if passed,
 *               false either
 * @param (string) $expected the expected result
 * @return (void)
 */
function store_result($passed, $expected) {

  // Get current test id
  $test_id = $this->counter;
  
  // Store test result
  if ($passed) {
    // Test passed
    if ($this->result[$test_id] == null) {
      $this->result[$test_id] = true;  // first test item in the current test
    } else {
      $this->result[$test_id] = $this->result[$test_id] && true;
    }
  } else {
    // Test failed
    $this->result[$test_id] = false;
    array_push($this->message[$test_id], $expected);
  }
}
}
/***************************************************************************

       $Log: Mtest.php,v $
       Revision 1.5  2006/02/04 11:19:53  jmfaure
       Add Mdoc and Mtest PHP5 versions (same processing as PHP4, only syntax corrections to run with E_STRICT).
       Modify banners and CVS data in classes (Mdoc.php and Mtest.php).
       Correct ;; line 50 in browse-documentation.php
       Correct <?php tag in config.php and browse-config.php
       Remove debugging stuff line 13 in view-internals.php and view-parsing.php
       Set $force_php4 to FALSE in config.php, browse-config.php and auto-documentation.php
       Set error reporting to E_STRICT in config.php, browse-config.php, auto-documentation.php and test-suite.php
       Force PHP_SELF URLs as /phpManta/Mdoc/test-suite.php in test-suite.php, to make in work even if phpManta folder is moved.

       Revision 1.4  2006/01/10 15:26:43  jmfaure
       Remove non-sense history in CVS Log from Class2.
       Change CVS keywords on top of Mdoc and Mtest.
       Modify test-suite.php to reflect Class2 changes.

       Revision 1.3  2006/01/10 14:33:19  jmfaure
       Add @experimental in Mtest comment.

       Revision 1.2  2006/01/10 14:25:18  jmfaure
       Delete @version and @author in Mdoc and Mtest.
       Add CVS archive data at end of Mtest.

 **************************************************************************/
?>